﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Web.Mvc;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebSite.Controllers;

namespace ControleRepresentante.UnitTests
{
    public static class TestScenarioFabricaHelper
    {
        public static void DeleteFabrica(this TestScenario testScenario, Guid fabricaId)
        {
            IFabricaRepository fabricaRepository = testScenario.RepositoryProvider.GetRepository<IFabricaRepository>();
            StatisticsBase statistics;
            int countBefore = fabricaRepository.GetModels(out statistics).Count();
            using (FabricaController fabricaController = new FabricaController(testScenario.RepositoryProvider, testScenario.SessionConfiguration, testScenario.ControllerExtensionProvider))
            {
                fabricaController.Delete(fabricaId);
                fabricaController.Delete(fabricaId, null);
                Assert.AreEqual(countBefore - 1, fabricaRepository.GetModels(out statistics).Count());
            }
        }

        public static Guid CreateFabrica(this TestScenario testScenario, Fabrica fabrica)
        {
            IFabricaRepository fabricaRepository = testScenario.RepositoryProvider.GetRepository<IFabricaRepository>();
            StatisticsBase statistics;
            int countBefore = fabricaRepository.GetModels(out statistics).Count();
            using (FabricaController fabricaController = new FabricaController(testScenario.RepositoryProvider, testScenario.SessionConfiguration, testScenario.ControllerExtensionProvider))
            {
                fabricaController.Create();
                foreach (Contato contato in fabrica.Contatos)
                {
                    fabricaController.ContatoInsert(contato.Tipo.ToString(), contato.Valor, contato.Observacao, contato.Principal);
                }
                foreach (Conta conta in fabrica.Contas)
                {
                    fabricaController.ContaInsert(conta.Banco, conta.Agencia, conta.Numero, conta.Observacao, conta.Principal);
                }
                foreach (Endereco endereco in fabrica.Enderecos)
                {
                    fabricaController.EnderecoInsert(endereco.Tipo.ToString(), endereco.Rua, endereco.Numero,
                                                      endereco.Complemento, endereco.Bairro, endereco.CEP,
                                                      endereco.Cidade, endereco.Estado, endereco.Observacao, endereco.Principal);
                }
                NameValueCollection collection = new NameValueCollection();
                foreach (AttributeValue attributeValue in fabrica.AttributeValues)
                {
                    collection.Add("_" + attributeValue.Attribute.Name, attributeValue.Value);
                }
                if (fabricaRepository.GetRepresentante().UseJolitex)
                {
                    collection.Add("isJolitex", fabrica.FabricaJolitex != null ? fabrica.FabricaJolitex.IsJolitex.ToString() : "false");
                }
                FormCollection formCollection = new FormCollection(collection);
                ActionResult actionResult = fabricaController.Create(fabrica.Nome, fabrica.CNPJ, fabrica.InscricaoEstadual, formCollection);
                IEnumerable<Fabrica> fabricas = fabricaRepository.GetModels(out statistics);
                Assert.AreEqual(countBefore + 1, fabricas.Count());
                Fabrica addedFabrica = fabricas.FirstOrDefault(x => x.Nome == fabrica.Nome);
                Assert.AreEqual(fabrica.Nome, addedFabrica.Nome);
                Assert.AreEqual(fabrica.CNPJ, addedFabrica.CNPJ);
                Assert.AreEqual(fabrica.InscricaoEstadual, addedFabrica.InscricaoEstadual);
                Assert.AreEqual(fabrica.Contatos.Count(), addedFabrica.Contatos.Count());
                foreach (Contato contato in fabrica.Contatos)
                {
                    Contato addedContato = addedFabrica.Contatos.Single(x => x.Valor == contato.Valor);
                    Assert.AreEqual(contato.Tipo, addedContato.Tipo);
                    Assert.AreEqual(contato.Valor, addedContato.Valor);
                    Assert.AreEqual(contato.Observacao, addedContato.Observacao);
                    Assert.AreEqual(contato.Principal, addedContato.Principal);
                }
                Assert.AreEqual(fabrica.Contas.Count(), addedFabrica.Contas.Count());
                foreach (Conta conta in fabrica.Contas)
                {
                    Conta addedConta = addedFabrica.Contas.Single(x => x.Numero == conta.Numero);
                    Assert.AreEqual(conta.Agencia, addedConta.Agencia);
                    Assert.AreEqual(conta.Banco, addedConta.Banco);
                    Assert.AreEqual(conta.Numero, addedConta.Numero);
                    Assert.AreEqual(conta.Observacao, addedConta.Observacao);
                    Assert.AreEqual(conta.Principal, addedConta.Principal);
                }
                Assert.AreEqual(fabrica.Enderecos.Count(), addedFabrica.Enderecos.Count());
                foreach (Endereco endereco in fabrica.Enderecos)
                {
                    Endereco addedEndereco = addedFabrica.Enderecos.Single(x => x.Rua == endereco.Rua);
                    Assert.AreEqual(endereco.Tipo, addedEndereco.Tipo);
                    Assert.AreEqual(endereco.Rua, addedEndereco.Rua);
                    Assert.AreEqual(endereco.Numero, addedEndereco.Numero);
                    Assert.AreEqual(endereco.Complemento, addedEndereco.Complemento);
                    Assert.AreEqual(endereco.Bairro, addedEndereco.Bairro);
                    Assert.AreEqual(endereco.CEP, addedEndereco.CEP);
                    Assert.AreEqual(endereco.Cidade, addedEndereco.Cidade);
                    Assert.AreEqual(endereco.Estado, addedEndereco.Estado);
                    Assert.AreEqual(endereco.Observacao, addedEndereco.Observacao);
                    Assert.AreEqual(endereco.Principal, addedEndereco.Principal);
                }
                Assert.AreEqual(fabrica.AttributeValues.Count(), addedFabrica.AttributeValues.Count());
                foreach (AttributeValue attributeValue in fabrica.AttributeValues)
                {
                    AttributeValue addedAttributeValue = addedFabrica.AttributeValues.Single(x => x.Attribute.Name == attributeValue.Attribute.Name);
                    Assert.AreEqual(attributeValue.Value, addedAttributeValue.Value);
                }
                Assert.IsInstanceOfType(actionResult, typeof(RedirectToRouteResult));
                RedirectToRouteResult redirectToRouteResult = (RedirectToRouteResult)actionResult;
                Assert.AreEqual("Details", redirectToRouteResult.RouteValues["action"]);
                Assert.AreEqual(addedFabrica.Id, redirectToRouteResult.RouteValues["id"]);
                return addedFabrica.Id;
            }
        }

        internal static Guid CreateFabrica(this TestScenario testscenario, string nome)
        {
            return testscenario.CreateFabrica(new Fabrica {Nome = nome, CNPJ = "cnpj", InscricaoEstadual = "inscricao"});
        }
    }
}